﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Collections.Generic;
using System.Web.Management;

namespace dao.commons
{
    public class BaseDao
    {
        protected SqlConnection Conexion = new SqlConnection();
        protected SqlCommand Cmd = new SqlCommand();
        protected SqlTransaction Transaccion = null;

        public string StringConexion = WebConfigurationManager.ConnectionStrings["StringConexion"].ConnectionString;
        
        protected string CampoBaja = "DADO_BAJA";
        protected string NombreTabla;
        protected string NombrePk;
        protected bool PkAutonumerica;

        public BaseDao(string _nombreTabla, string _nombrePk, bool _pkAutonumerica)
        {
            NombreTabla = _nombreTabla;
            NombrePk = _nombrePk;
            PkAutonumerica = _pkAutonumerica;
        }

        //METODOS DE SOPORTE GENERALES
        protected void Conectar()
        {
            if (Conexion.State == ConnectionState.Open)
            {
                Conexion.Close();
            }
            Conexion.ConnectionString = StringConexion;
            Conexion.Open();
            Cmd.Connection = Conexion;
            Cmd.CommandType = CommandType.Text;
        }

        private DataTable EjecutarReader(string consulta)
        {
            DataTable tabla = new DataTable();

            Conectar();
            Cmd.CommandText = consulta;
            tabla.Load(Cmd.ExecuteReader(CommandBehavior.CloseConnection));
            Conexion.Close();

            return tabla;
        }

        
        public SqlDataReader traerDatosConsulta(string consulta)
        {
            Conectar();
            SqlDataReader dr = null;
            try
            {
                Cmd.CommandText = consulta;
                dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
                return dr;
            }
            catch (Exception)
            {
                return dr;
            }

        }

        private void EjecutarNonQuery(string consulta)
        {
            Conectar();
            Cmd.CommandText = consulta;
            Cmd.ExecuteNonQuery();
            Conexion.Close();
        }

        private DataTable LeoEstructura()
        {
            string comando = null;
            DataTable tabla = new DataTable();
            comando = "select top 1 * from " + NombreTabla;
            tabla = EjecutarReader(comando);
            return tabla;
        }


        //METODOS BASE
        public SqlDataReader ObtenerTodo()
        {
            Conectar();
            SqlDataReader dr = null;
            try
            {
                Cmd.CommandText = "select * from " + NombreTabla;
                Cmd.Parameters.Add(new SqlParameter("@nombreTabla", NombreTabla));
                dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
                return dr;
            }
            catch (Exception e)
            {
                throw new SqlExecutionException("Error al obtener todo BaseDao", e);
            }
        }

        public SqlDataReader ObtenerActivos()
        {
            Conectar();
            SqlDataReader dr = null;
            try
            {
                Cmd.CommandText = "select * from " + NombreTabla + " where "+ CampoBaja + " = 0";
                dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
                return dr;
            }
            catch (Exception e)
            {
                throw new SqlExecutionException("Error al obtener activos en BaseDao", e);
            }
       }

        public SqlDataReader ObtenerPorId(int id)
        {
            Conectar();
            SqlDataReader dr = null;
            try
            {
                Cmd.CommandText = "select * from " + NombreTabla + " where " + NombrePk + " = " + id;
                //Cmd.Parameters.Add(new SqlParameter("@nombreTabla", NombreTabla));
                //Cmd.Parameters.Add(new SqlParameter("@nombrePk", NombrePk));
                //Cmd.Parameters.Add(new SqlParameter("@id", id));
                dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
                return dr;
            }
            catch (Exception e)
            {
                throw new SqlExecutionException("Error al obtener por Id BaseDao", e);
            }
        }

        public bool Existe(int pk)
        {
            Conectar();
            try
            {
                Cmd.CommandText = "select * from @nombreTabla where @nombrePk = @pk";
                Cmd.Parameters.Add(new SqlParameter("@nombreTabla", NombreTabla));
                Cmd.Parameters.Add(new SqlParameter("@nombrePk", NombrePk));
                Cmd.Parameters.Add(new SqlParameter("@pk", pk));
                SqlDataReader dr = Cmd.ExecuteReader();
                if (dr.Read())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                throw new SqlExecutionException("Error al verificar si existe BaseDao", e);
            }
            finally
            {
                Conexion.Close();
            }
        }

        public bool ExistePorCampoNoPk(string nombreTabla, string campo, string valor)
        {
            Conectar();
            try
            {
                Cmd.CommandText = "select * from " + nombreTabla + " WHERE " +campo+" LIKE '%" + valor+"%'";
                
                SqlDataReader dr = Cmd.ExecuteReader();
                if (dr.Read())
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                throw new SqlExecutionException("Error al verificar si existe por campo no pk BaseDao", e);
            }
            finally
            {
                Conexion.Close();
            }
        }


        public void Eliminar(int pk)
        {
            Conectar();
            try
            {
                Cmd.CommandText = "Update " + NombreTabla + " Set " + CampoBaja + " = 1 Where " + NombrePk + " = " + pk;
                Cmd.Parameters.Add(new SqlParameter("@nombreTabla", NombreTabla));
                Cmd.Parameters.Add(new SqlParameter("@campoBaja", CampoBaja));
                Cmd.Parameters.Add(new SqlParameter("@nombrePk", NombrePk));
                Cmd.Parameters.Add(new SqlParameter("@pk", pk));
                Cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                throw new SqlExecutionException("Error al eliminar por Id BaseDao", e);
            }
            finally
            {
                Conexion.Close();
            }
        }

  
        public void Insertar(string valores)
        {
            string txtInsert = "";
            txtInsert = this.ArmoInsert();
            txtInsert += this.asigno_valores_insert(valores);
            this.Conectar();
            this.Cmd.CommandText = txtInsert;
            Cmd.ExecuteNonQuery();
            this.Conexion.Close();
        }

        public void Insertar(string valores, SqlConnection con, SqlTransaction trans)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Transaction = trans;
            string txtInsert = "";
            txtInsert = this.ArmoInsert();
            txtInsert += this.asigno_valores_insert(valores);
            cmd.Connection = con;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = txtInsert;
            cmd.ExecuteNonQuery();
        }

        public void Modificar(string valores, string restriccion)
        {
            string update = "UPDATE " + NombreTabla + " SET ";
            string set = null;
            string _restriccion = null;
            set = ArmaSetUpdate(valores);
            _restriccion = ArmarRestriccionUpdate(restriccion);
            if (_restriccion == "error")
            {
                return;
            }
            update += set + _restriccion;
            Conectar();
            Cmd.CommandText = update;
            Cmd.ExecuteNonQuery();
            Conexion.Close();
        }


        //METODOS DE SOPORTE PARA INSERT, UPDATE
        private string ArmarRestriccionUpdate(string restriccion)
        {
            System.Data.DataTable objetoTabla = null;
            //tabla que contiene la estructura en la base 
            int contador = 0;
            //contador de bucle()
            int c = 0;
            //para recorrer las columas buscando una 
            int coma = 0;
            //ubicacion de la(",")
            int igual = 0;
            //ubicación del("=")
            string txt_origen = "";
            //texto origen 
            string nombre_campo = "";
            //campo a buscar()
            string valor = "";
            //valor del campo Dim txt As String = "" 'texto que se va formando para el insert 
            string txt = "";
            //texto que se va formando para el insert
            string tipo_dato = "";
            bool estado = true;
            bool encontro = false;
            bool primeraVez = true;
            objetoTabla = this.LeoEstructura();
            txt_origen = restriccion.ToUpper().Trim();

            if (PkAutonumerica == true)
            {
                contador = 1;
            }
            else
            {
                contador = 0;
            }

            while (estado)
            {
                igual = txt_origen.IndexOf("=");
                coma = (txt_origen.IndexOf(",") == -1 ? txt_origen.Length : txt_origen.IndexOf(","));
                if (txt_origen.IndexOf(",") == -1)
                {
                    estado = false;
                }
                nombre_campo = txt_origen.Substring(0, igual).Trim();
                valor = txt_origen.Substring(igual + 1, coma - igual - 1).Trim();
                tipo_dato = objetoTabla.Columns[contador].DataType.ToString();
                for (c = 0; c <= objetoTabla.Columns.Count - 1; c++)
                {
                    if (nombre_campo.Trim() == objetoTabla.Columns[c].Caption.ToUpper().Trim())
                    {
                        tipo_dato = objetoTabla.Columns[c].DataType.ToString();
                        encontro = true;
                    }
                }
                if (encontro)
                {
                    if (primeraVez)
                    {
                        txt += "WHERE " + nombre_campo + " = " + acomodo_al_tipo_dato(valor, tipo_dato) + "\r";
                        primeraVez = false;
                    }
                    else
                    {
                        txt += " AND " + nombre_campo + " = " + acomodo_al_tipo_dato(valor, tipo_dato) + "\r";
                    }
                }
                else
                {
                    txt = "error";
                    break;
                }
                if (estado == true)
                {
                    txt_origen = txt_origen.Substring(coma + 1);
                }
            }
            return txt;
        }

        private string ArmaSetUpdate(string valores)
        {
            System.Data.DataTable objetoTabla = null;
            //tabla que contiene la estructura en la base 
            int contador = 0;
            //contador de bucle()
            int campo = 0;
            //ubicación del(campo)
            int coma = 0;
            //ubicacion de la(",")
            int igual = 0;
            //ubicación del("=")
            string txt_origen = "";
            //texto origen 
            string nombre_campo = "";
            //campo a buscar()
            string valor = "";
            //valor del campo()
            string txt = "";
            //texto que se va formando para el insert 
            string tipo_dato = "";

            if (PkAutonumerica == true)
            {
                contador = 1;
            }
            else
            {
                contador = 0;
            }

            objetoTabla = this.LeoEstructura();
            txt_origen = valores.ToUpper().Trim();
            while (objetoTabla.Columns.Count > contador)
            {
                nombre_campo = objetoTabla.Columns[contador].Caption.ToUpper().Trim();
                tipo_dato = objetoTabla.Columns[contador].DataType.ToString();
                campo = txt_origen.IndexOf(nombre_campo);
                if (campo != -1)
                {
                    igual = txt_origen.IndexOf("=", campo);
                    coma = txt_origen.IndexOf(",", campo);
                }
                else
                {
                    igual = -1;
                    coma = -1;
                }
                if (campo != -1)
                {
                    igual = txt_origen.IndexOf("=", campo);
                    coma = txt_origen.IndexOf(",", campo);
                    if (coma != -1)
                    {
                        valor = objetoTabla.Columns[contador].Caption + "=";
                        valor += this.acomodo_al_tipo_dato(txt_origen.Substring(igual + 1, coma - igual - 1), tipo_dato);
                    }
                    else
                    {
                        valor = objetoTabla.Columns[contador].Caption + "=";
                        valor += this.acomodo_al_tipo_dato(txt_origen.Substring(igual + 1), tipo_dato);
                    }
                }
                else
                {
                    valor = "null";
                }
                txt += valor;
                contador += 1;
                if (contador < objetoTabla.Columns.Count)
                {
                    txt += ", ";
                }
            }
            txt += " ";
            return txt;

        }
       

        private string ArmoInsert()
        {
            int i= 0;
            int contador = 0;
            System.Data.DataTable tabla = null;

            if (PkAutonumerica == true)
            {
                contador = 1;
            }
            else
            {
                contador = 0;
            }

            string txt = "";
            tabla = this.LeoEstructura();
            txt = "insert into " + this.NombreTabla + " (";
            while (tabla.Columns.Count > contador)
            {

                txt += tabla.Columns[contador].Caption;
                contador += 1;
                if (contador < tabla.Columns.Count)
                {
                    txt += ", ";
                }
            }
            txt += ") values (";
            return txt;
        }

        private string asigno_valores_insert(string txtInsertar)
        {
            System.Data.DataTable objetoTabla = null;
            //tabla que contiene la estructura en la base 
            int contador = 0;
            //contador de bucle()
            int campo = 0;
            //ubicación del(campo)
            int coma = 0;
            //ubicacion de la(",")
            int igual = 0;
            //ubicación del("=")
            string txt_origen = "";
            //texto origen 
            string nombre_campo = "";
            //campo a buscar()
            string valor = "";
            //valor del campo()
            string txt = "";
            //texto que se va formando para el insert 
            string tipo_dato = "";

            if (PkAutonumerica == true)
            {
                contador = 1;
            }
            else
            {
                contador = 0;
            }

            objetoTabla = this.LeoEstructura();
            txt_origen = txtInsertar.ToUpper().Trim();
            while (objetoTabla.Columns.Count > contador)
            {
                nombre_campo = objetoTabla.Columns[contador].Caption.ToUpper().Trim();
                tipo_dato = objetoTabla.Columns[contador].DataType.ToString();
                campo = txt_origen.IndexOf(nombre_campo);
                if (campo != -1)
                {
                    igual = txt_origen.IndexOf("=", campo);
                    coma = txt_origen.IndexOf(",", campo);
                }
                else
                {
                    igual = -1;
                    coma = -1;
                }
                if (campo != -1)
                {
                    igual = txt_origen.IndexOf("=", campo);
                    coma = txt_origen.IndexOf(",", campo);
                    if (coma != -1)
                    {
                        valor = this.acomodo_al_tipo_dato(txt_origen.Substring(igual + 1, coma - igual - 1), tipo_dato);
                    }
                    else
                    {
                        valor = this.acomodo_al_tipo_dato(txt_origen.Substring(igual + 1), tipo_dato);
                    }
                }
                else
                {
                    valor = "null";
                }
                txt += valor;
                contador += 1;
                if (contador < objetoTabla.Columns.Count)
                {
                    txt += ", ";
                }
            }
            txt += ")";
            return txt;
        }

        private string acomodo_al_tipo_dato(string texto, string tipo_dato)
        {
            switch (tipo_dato)
            {
                case "System.String":
                    return "'" + texto + "'";
                case "System.Int16":
                    return texto;
                case "System.Int32":
                    return texto;
                case "System.Int64":
                    return texto;
                case "System.Byte":
                    return texto;
                case "System.Double":
                    return texto;
                case "System.Decimal":
                    return texto;
                case "System.DateTime":
                    return "'" + texto + "'";
                case "System.DateTimeKind":
                    return "'" + texto + "'";
                default:
                    return texto;
            }
        }
    }
}
